package input

import (
	"github.com/hpcloud/tail"
	"kuafu/core/plugin"
	"kuafu/progress/log"
	"regexp"
	"strconv"
	"strings"
	"time"
)

var (
	head   = "# Time"
	end    = ";"
	reg, _ = regexp.Compile(`#\s+Time:\s+(?P<Time>.+)\s?#\s+User@Host:\s+(?P<user>.+)\[.+\]\s+@\s+\[(?P<proxyHost>[\w|\.|\s]+)\]\s+Id:\s+(?P<threadID>\d+)\s?#\s+Query_time:\s+(?P<queryTime>\w+\.?\w+)\s+Lock_time:\s+(?P<lockTime>\w+\.?\w+)\s+Rows_sent:\s+(?P<rowsSent>\d+)\s+Rows_examined:\s+(?P<rowsExamined>\d+)\s?(use\s+(?P<use>.*);)?\s?SET\s+timestamp=(?P<sqlTimestamp>\d+);\s?(?P<sqlText>[\W\w]+;)`)
	loc    = time.Local
)

type LogParserPlugin struct {
	entryText string
}

func (parser *LogParserPlugin) Process(line *tail.Line) *plugin.LogEntry {

	if strings.HasPrefix(line.Text, head) {
		if parser.entryText != "" {
			logEntry := parseAndFlush(parser, line)
			parser.entryText = line.Text
			return logEntry
		}
		parser.entryText = line.Text
		return nil
	}

	parser.entryText += line.Text
	complete := strings.HasSuffix(line.Text, end) && !strings.HasPrefix(line.Text, "SET timestamp") && !strings.HasPrefix(line.Text, "use ")
	if complete {
		logEntry := parseAndFlush(parser, line)
		if logEntry != nil {
			parser.entryText = ""
			return logEntry
		}
	}
	return nil
}

func parseAndFlush(parser *LogParserPlugin, line *tail.Line) *plugin.LogEntry {
	if parser.entryText == "" {
		return nil
	}

	fullResult := reg.FindAllStringSubmatch(parser.entryText, -1)
	if fullResult == nil {
		log.Log.Errorf("解析数据错误: %s", parser.entryText)
		return nil
	}

	currentEntry := new(plugin.LogEntry)
	currentEntry.Time = plugin.LocalTime(line.Time)
	if len(fullResult) == 0 {
		log.Log.Errorf("解析数据错误: %s", parser.entryText)
		return nil
	}
	result := fullResult[0]
	if len(result) < 13 {
		log.Log.Errorf("解析数据错误: %s", parser.entryText)
		return nil
	}
	if len(result[1]) < 19 {
		log.Log.Errorf("原始时间格式错误: %s", result[1])
		return nil
	}
	timeStr := result[1][0:19]
	location, err := time.ParseInLocation("2006-01-02T15:04:05", timeStr, loc)
	logTime := plugin.LocalTime(location)
	if err != nil {
		log.Log.Errorf("时间格式错误: %s", timeStr)
		currentEntry.LogTime = plugin.LocalTime{}
	} else {
		currentEntry.LogTime = logTime
	}
	currentEntry.User = result[2]
	currentEntry.Host = result[3]
	currentEntry.Id = result[4]
	currentEntry.QueryTime, _ = strconv.ParseFloat(result[5], 32)
	currentEntry.LockTime, _ = strconv.ParseFloat(result[6], 32)
	currentEntry.RowsSent, _ = strconv.Atoi(result[7])
	currentEntry.RowsExamined, _ = strconv.Atoi(result[8])
	currentEntry.Sql = result[12]
	return currentEntry
}
